---
title: 服务治理
---
微服务中的服务治理是通过服务注册、发现、路由、负载均衡、监控、安全认证等手段，保证微服务系统的各个服务可以高效协同工作，以提高服务的可用性、可靠性、安全性和可维护性。

## 微服务生命周期各个状态的流转

:::note
假设系统有两个微服务（服务 A 和 服务 B），每一个微服务有 10 个虚拟节点。如果此时微服务 A 想要调用 微服务 B ，该怎么发起这个调用？
:::



服务治理要解决的首要任务就是**服务注册**与**服务发现**，通过这两项技术，就能让微服务之间发起面对面的直接调用。

为了让服务 A 拿到服务 B 的机器清单，需要搭建一个**中心化的注册中心**，服务 B 只要将自己的信息添加到注册中心，服务 A 就能从注册中心获取到服务 B 的所有节点信息。



![image-20230402013333524](https://img.wkq.pub/pic/image-20230402013333524.png)

如上图： 服务 B 集群首先向注册中心发起了注册，将自己的地址信息上报到注册中心，这个过程就是**服务注册**。

接下来，每隔一段时间，服务 A 就会从注册中心获取服务 B 集群的注册列表，或者由注册中心将服务列表的变动推送给服务 A ，这个过程叫做**服务发现**。最后，服务 A 根据本地负载均衡策略，从服务列表中选取某一个服务 B 的节点，发起服务调用。



在这个过程中，**注册中心是一个中心化的信息管理者**，所有的微服务节点在启动后都会将自己的地址信息添加到注册中心。在服务注册的过程中，有两个关键信息是最重要的：

1. **服务名称**： 服务名称通常默认是 spring.application.name 属性。其它服务需要根据服务名称找到对应的服务节点列表。
2. **地址信息**： 包括服务的 IP 地址和端口号。

通过上面这两个信息，调用方就能精准定位到目标微服务。

通过 服务注册与发现，已经能够实现端到端的调用链路，但这个方案还缺少了**异常容错**的机制。

如果服务 B 集群因为未知的网络异常导致无法响应服务，这时候 服务 A 向服务 B 发起了服务调用，就会发生超时或者服务无响应的异常情况。那如何在服务治理方案中规避这类问题呢？

业界通用的解决方案是 ”healthcheck“ 或者 ”heartbeat“ 。注册中心可以通过这种机制来标记异常服务，这样一来，Client 端在发送请求时就能避开异常节点。

![image-20230402015643305](https://img.wkq.pub/pic/image-20230402015643305.png)

所有的服务都要在注册中心进行注册，而且每个节点都需要每隔一段时间向注册中心同步自己当前的状态，这个过程被称为 heartbeat（心跳）。

如果节点持续发送消息，则一切正常，服务可以被发现；如果注册中心在一段时候内没有收到 Client 的心跳包，注册中心就会将这个节点标记为下线状态，进而将该服务从服务列表从剔除。

服务剔除是由注册中心主导的”被动下线“，此外，当服务节点关闭或者重启的时候，通过发送一条”服务下线“指令到注册中心，将当前节点标记为下线状态。

## Nacos 体系结构

Nacos 有三个核心知识点：领域模型、数据模型和基本架构。

### 领域模型

Nacos 领域模型描述了服务与实例之间的边界和层级关系，Nacos 的服务领域模型是以服务为维度构建起来的，这里的服务是指微服务的服务名。

服务是Nacos 中位于最上层的概念，在服务之下，还有集群和实例的概念。



![21d3938ce122a48652397c329b361948](https://img.wkq.pub/pic/21d3938ce122a48652397c329b361948.webp)

Nacos 领域模型从上到下分为了 服务、集群和实例三层

#### 1. 服务

在服务这个层级可以配置元数据和服务保护阈值等信息。服务阈值是一个 0~1 之间的数字，当服务的健康实例数与总实例数的比例小于这个阈值的时候，说明能提供服务的机器已经没多少了。这时候 Nacos 就会开启保护模式，不再主动剔除服务实例，同时还会将不健康的服务实例也返回给消费者。

尽管这样做可能造成请求失败，但间接保证了最低限度的服务可用性。

#### 2. 集群

一个服务由很多服务实例组成，在每个服务实例启动的时候，我们可以设置它所属的集群，在集群这个层级上，也可以配置元数据。除此之外，还可以为持久化节点设置健康检查模式。



所谓持久化节点，是一种会保存到 Nacos 服务端的实例，即便该实例的客户端进程没有在运行，实例也不会被删除，只不过 Nacos 会将这个持久化节点状态标记为不健康，Nacos 采用一种”主动探活“ 的方式来对持久化节点做健康检查。



除了持久化节点以外，其它服务节点在 Nacos 中以 ”临时节点”的方式存在，它是默认的服务注册方式。临时节点通过主动发送 heartbeat 请求向服务器报告自己的状态。

#### 3. 实例

实例就是服务节点，可以在 Nacos 控制台查看每个实例的 IP 地址和端口，编辑实例的元数据信息、修改它的上下线状态或者配置路由权重等。

在这三个层级上都有“元数据”这一数据结构，可以把它理解为一组包含了服务描述信息（如服务版本等）和自定义标签的数据结构。Client 端通过服务发现技术可以获取到每个服务实例的元数据，可以将自定义的属性加入到元数据并在 Client 端实现某些定制化的业务场景。

### 数据模型

:::tip

服务调用方是如何定位到领域模型中的服务实例的？这就要提高 Nacos 的领域模型了。

:::

Nacos 的领域模型有三个层级，分别是 Namespace 、Group、和 Service/DateId，如下图：



![e89a90d5cdb2d4929a8e44cf5c747fee](https://img.wkq.pub/pic/e89a90d5cdb2d4929a8e44cf5c747fee.webp)

#### 1. Namespace

它是最顶层的数据结构，可以用它来区分开发环境、生产环境等不同的环境。默认情况下，所有的服务都部署到一个叫做 “public” 的公共命名空间；

#### 2. Group

在命名空间下有一个分组结构，默认情况下，所有的微服务都属于 ”DEFAULT_GROUP“ 分组，不同分组间的微服务是互相隔离的。

#### 3. Service/DataID

在 Group 分组之下，就是具体的微服务了。



通过 Namespace + Group + Service/DataID ,就可以精准定位到一个具体的微服务。

### Nacos 基本架构

Nacos 的基本功能有两个，一个是 **Naming Service**，也就是用来做服务发现的模块；另一个是 **Config Service**，用来提供配置管理。

![d3a2227dcdab8b7ddc786c9653c6bc59](https://img.wkq.pub/pic/d3a2227dcdab8b7ddc786c9653c6bc59.webp)

Provider APP 和 Consumer APP 通过 Open API 和 Nacos 服务器的核心模块进行通信。这里的 Open API 是一组对外暴露的 RESTful 风格的 HTTP 接口。



在 Nacos 的核心模块里，Naming Service 提供了将对象和实例的”名字“映射到元数据的功能，这是服务发现的基础功能之一。

:::tip

我想要调用 OrderService，我手里有这个服务的 Namespace 和 Group 信息，那么我就可以通过 Naming Service 定位到这个服务对应的实例列表。同理，如果我有一个 DNS 名称，同样可以借助 Naming Service 获取 DNS 背后配置的 IP 列表。以上两个场景就分别对应了服务发现和 DNS 功能，这两个场景都是 Naming Service 的核心场景。

:::

Nacos 还有一个相当重要的模块，**Nacos Core**。它可以提供一系列的平台基础功能，下面是 Nacos Core 中包含的重要功能：

![d0c78d0c0f2bb72c45788a5c2d423512](https://img.wkq.pub/pic/d0c78d0c0f2bb72c45788a5c2d423512.webp)

Nacos 内部支持两种一致性协议，一种是侧重一致性的 Raft 协议，基于集群中选举出来的 Leader 节点进行数据写入；另一种是针对临时节点的 Distro 协议，它是一个侧重可用性（或最终一致性）的分布式一致性协议。

